﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ConjureBivouac2012.Object;
using Microsoft.Xna.Framework;

namespace ConjureBivouac2012.Mathematics
{
    public class Phasik
    {
        public static bool Collision(Entity ship, Entity otherShip)
        {
            float distance = (ship.sprite.Position - otherShip.sprite.Position).Length();
            distance = distance - ship.GetRadius() - otherShip.GetRadius();
            if (distance < 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public static void rebound(Entity entity, Entity otherEntity)
        {
            //Cases where there are no rebouns (bullet-bullet, enemy-bullet, powerups-anything)
            if ((entity is AbstractBullet && otherEntity is AbstractBullet) ||
                 (otherEntity is AbstractBullet && entity is AbstractEnemy)
                || (entity is AbstractBullet && otherEntity is AbstractEnemy) ||
                entity is AbstractPowerUp || otherEntity is AbstractPowerUp)
            {
                return;
            }

            Entity e1 = entity;
            Entity e2 = otherEntity;

            if ((entity.GetDirection().X == 0 && entity.GetDirection().Y == 0) || otherEntity is AbstractBullet)
            {
                e1 = otherEntity;
                e2 = entity;
            }

            Vector2 e1Position = e1.sprite.Position - e1.GetDirection()*100;

            // Calculate the tangent of the entity direction and the collision to otherEntity 
            Vector2 tangent = new Vector2();
            tangent.Y = -(e1Position.X - e2.sprite.Position.X);
            tangent.X = e1Position.Y - e2.sprite.Position.Y;
            tangent.Normalize();

            // Relative velocity of the entity
            Vector2 relvel = new Vector2(0 - e1.GetDirection().X, 0 - e1.GetDirection().Y);

            // length of the relative velocity and the tangent
            float lenght = Vector2.Dot(relvel, tangent);

            Vector2 componentTangent = new Vector2();
            Vector2.Multiply(ref tangent, lenght, out componentTangent);
            Vector2 perpendiculaire = relvel - componentTangent;

            // Set new direction
            Vector2 newDirection1 = new Vector2();

            int modif = 2;

            newDirection1.X = e1.GetDirection().X + modif * perpendiculaire.X;
            newDirection1.Y = e1.GetDirection().Y + modif * perpendiculaire.Y;
            
            if(e1 is AbstractEnemy && e2 is AbstractEnemy)
            {
                //e2.SetDirection(-newDirection1);
            }

            if (e2 is AbstractEnemy) e2.SetDirection(-newDirection1);

            if (e1 is AbstractBullet) e1.setVelocity(new Vector2(300,300));
            else if (e2 is AbstractBullet) e2.setVelocity(new Vector2(300,300));


            e1.SetDirection(newDirection1);
        }

        public static Vector2 GetFireDirection(Entity player, Entity ennemy)
        {
            Vector2 direction;
            direction = player.sprite.Position - ennemy.sprite.Position;
            direction.Normalize();

            return direction;
        }

        public static bool IsCollidesWithAEntity(List<Entity> list, Vector2 spawnPos, float spawnRadius)
        {
            foreach (Entity e in list)
            {
                if (e is AbstractEnemy || e is AbstractVehicule)
                {
                    if (IsCollidesWithSpawn(spawnPos, spawnRadius, e))
                    {
                        return true;
                    }
                }
            }

            return false;
        }

        private static bool IsCollidesWithSpawn(Vector2 spawnPos, float spawnRadius, Entity e)
        {
            bool collides = false;

            float distance = (e.sprite.Position - spawnPos).Length() - e.GetRadius() - spawnRadius;

            collides = distance <= 5;

            return collides;
        }

        public static bool IsPositionWithinBounds(Vector2 pos, float radius)
        {
            float leftBound = radius;
            float topBound = radius;

            float rightBound = GameInfo.GetInstance().GetDevice().Viewport.Width - radius;
            float bottomBound = GameInfo.GetInstance().GetDevice().Viewport.Height - radius;

            if (pos.X > rightBound)
            {
                return false;
            }
            else if (pos.X < leftBound)
            {
                return false;
            }

            if (pos.Y > bottomBound)
            {
                return false;
            }
            else if (pos.Y < topBound)
            {
                return false;
            }

            return true;
        }
    }
}
